package vip.web3.api.aspect;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.redisson.api.RLock;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import vip.web3.api.annotation.RedisLock;
import vip.web3.api.service.base.RedissonClientApiService;
import vip.web3.common.exception.RRException;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

/**
 * 请求拦截
 */
@Slf4j
@Aspect
@Component
public class RedisLockIntercept {

    @Resource
    private RedissonClientApiService redissonClientApiService;

    @Pointcut("@annotation(redisLock)")
    public void pointcut(RedisLock redisLock) {

    }

    @Around("pointcut(redisLock)")
    public Object around(ProceedingJoinPoint joinPoint, RedisLock redisLock) throws Throwable {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String address = request.getParameter("address");
        if (StringUtils.isBlank(address)) {
            address = request.getHeader("token");
        }
        String key = redisLock.key() + ":" + address;
        RLock rLock = redissonClientApiService.getLock(key);
        try {
            //尝试加锁,最大等待时间3秒，上锁30秒自动解锁
            if (rLock.tryLock(redisLock.tryLockSecond(), redisLock.autoUnlockSecond(), TimeUnit.SECONDS)) {
                return joinPoint.proceed();
            } else {
                throw new RRException("客官慢一点", -1);
            }
        } finally {
            if (rLock != null && rLock.isLocked() && rLock.isHeldByCurrentThread()) {
                rLock.unlock();
            }
        }
    }


}
